using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.Win32;

namespace MemGuardian
{
    /// <summary>
    /// 内存清理器类
    /// 参考neicun项目实现，根据设置窗口的选项执行内存释放功能
    /// 使用Windows API进行系统级内存清理
    /// </summary>
    public class MemoryCleaner
    {
        #region Windows API 声明

        /// <summary>
        /// 系统内存列表命令枚举
        /// 定义各种内存清理操作
        /// </summary>
        public enum SystemMemoryListCommand
        {
            MemoryEmptyWorkingSets = 1,           // 清空工作集
            MemoryFlushModifiedList = 2,          // 刷新修改页列表
            MemoryPurgeStandbyList = 3,           // 清空待机列表
            MemoryPurgeLowPriorityStandbyList = 4 // 清空低优先级待机列表
        }

        /// <summary>
        /// 系统信息类枚举
        /// 定义各种系统信息查询类型
        /// </summary>
        public enum SystemInformationClass
        {
            SystemMemoryListInformation = 0x50,                    // 内存列表信息
            SystemFileCacheInformationEx = 0x3F,                  // 文件缓存信息
            SystemRegistryReconciliationInformation = 0x8D,       // 注册表协调信息
            SystemCombinePhysicalMemoryInformation = 0x8E         // 合并物理内存信息
        }

        /// <summary>
        /// 系统文件缓存信息结构
        /// 用于设置文件缓存参数
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct SystemFileCacheInformation
        {
            public UIntPtr MinimumWorkingSet;
            public UIntPtr MaximumWorkingSet;
            public uint Flags;
        }

        /// <summary>
        /// 内存合并信息结构
        /// 用于合并物理内存列表
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct MemoryCombineInformationEx
        {
            public UIntPtr Handle;
            public UIntPtr PagesCombined;
        }

        /// <summary>
        /// 挂载管理器设备名称
        /// 用于访问卷缓存
        /// </summary>
        private const string MOUNTMGR_DEVICE_NAME = "\\Device\\MountMgr";

        /// <summary>
        /// 内存清理区域标志位定义
        /// 与neicun项目保持一致
        /// </summary>
        public const uint REDUCT_WORKING_SET = 0x01;                    // 工作集
        public const uint REDUCT_SYSTEM_FILE_CACHE = 0x02;             // 系统文件缓存
        public const uint REDUCT_STANDBY_PRIORITY0_LIST = 0x04;        // 待机列表（无优先级）
        public const uint REDUCT_STANDBY_LIST = 0x08;                  // 待机列表
        public const uint REDUCT_MODIFIED_LIST = 0x10;                 // 修改页列表
        public const uint REDUCT_COMBINE_MEMORY_LISTS = 0x20;          // 合并内存列表
        public const uint REDUCT_REGISTRY_CACHE = 0x40;                // 注册表缓存
        public const uint REDUCT_MODIFIED_FILE_CACHE = 0x80;           // 修改文件缓存

        /// <summary>
        /// 默认清理掩码
        /// 包含最常用的清理选项
        /// </summary>
        public const uint REDUCT_MASK_DEFAULT = REDUCT_WORKING_SET | REDUCT_SYSTEM_FILE_CACHE | 
                                               REDUCT_STANDBY_PRIORITY0_LIST | REDUCT_REGISTRY_CACHE | 
                                               REDUCT_COMBINE_MEMORY_LISTS | REDUCT_MODIFIED_FILE_CACHE;

        /// <summary>
        /// 所有清理选项掩码
        /// 包含所有可用的清理选项
        /// </summary>
        public const uint REDUCT_MASK_ALL = REDUCT_WORKING_SET | REDUCT_SYSTEM_FILE_CACHE |
                                          REDUCT_STANDBY_PRIORITY0_LIST | REDUCT_STANDBY_LIST |
                                          REDUCT_MODIFIED_LIST | REDUCT_COMBINE_MEMORY_LISTS |
                                          REDUCT_REGISTRY_CACHE | REDUCT_MODIFIED_FILE_CACHE;

        #endregion

        #region Windows API 导入

        /// <summary>
        /// 设置系统信息
        /// 用于执行各种系统级操作，包括内存清理
        /// </summary>
        /// <param name="SystemInformationClass">系统信息类</param>
        /// <param name="SystemInformation">系统信息缓冲区</param>
        /// <param name="SystemInformationLength">缓冲区长度</param>
        /// <returns>操作结果</returns>
        [DllImport("ntdll.dll")]
        private static extern int NtSetSystemInformation(
            SystemInformationClass SystemInformationClass,
            IntPtr SystemInformation,
            uint SystemInformationLength);

        /// <summary>
        /// 创建文件
        /// 用于访问挂载管理器设备
        /// </summary>
        [DllImport("ntdll.dll")]
        private static extern int NtCreateFile(
            out IntPtr FileHandle,
            uint DesiredAccess,
            ref ObjectAttributes ObjectAttributes,
            out IoStatusBlock IoStatusBlock,
            IntPtr AllocationSize,
            uint FileAttributes,
            uint ShareAccess,
            uint CreateDisposition,
            uint CreateOptions,
            IntPtr EaBuffer,
            uint EaLength);

        /// <summary>
        /// 关闭句柄
        /// 用于关闭文件句柄
        /// </summary>
        [DllImport("ntdll.dll")]
        private static extern int NtClose(IntPtr Handle);

        /// <summary>
        /// 刷新文件
        /// 用于刷新卷缓存
        /// </summary>
        [DllImport("ntdll.dll")]
        private static extern int NtFlushBuffersFile(IntPtr FileHandle, out IoStatusBlock IoStatusBlock);

        /// <summary>
        /// 对象属性结构
        /// 用于文件创建时的属性设置
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct ObjectAttributes
        {
            public uint Length;
            public IntPtr RootDirectory;
            public IntPtr ObjectName;
            public uint Attributes;
            public IntPtr SecurityDescriptor;
            public IntPtr SecurityQualityOfService;
        }

        /// <summary>
        /// IO状态块结构
        /// 用于异步IO操作
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct IoStatusBlock
        {
            public uint Status;
            public IntPtr Information;
        }

        /// <summary>
        /// Unicode字符串结构
        /// 用于字符串参数传递
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct UnicodeString
        {
            public ushort Length;
            public ushort MaximumLength;
            public IntPtr Buffer;
        }

        #endregion

        #region 公共方法

        /// <summary>
        /// 异步执行内存清理
        /// 根据注册表中的设置选项执行相应的内存清理操作
        /// </summary>
        /// <returns>清理结果信息</returns>
        public static async Task<MemoryCleanupResult> CleanMemoryAsync()
        {
            return await Task.Run(() =>
            {
                try
                {
                    // 检查是否以管理员权限运行
                    if (!IsRunningAsAdministrator())
                    {
                        return new MemoryCleanupResult
                        {
                            Success = false,
                            Message = "需要管理员权限才能执行内存清理操作",
                            MemoryFreed = 0
                        };
                    }

                    // 获取清理前的内存使用情况
                    var beforeMemory = GetMemoryUsage();

                    // 从注册表读取清理设置
                    var cleanupMask = GetCleanupMaskFromRegistry();

                    // 执行内存清理
                    var cleanupResult = PerformMemoryCleanup(cleanupMask);

                    // 获取清理后的内存使用情况
                    var afterMemory = GetMemoryUsage();

                    // 计算释放的内存
                    var memoryFreed = beforeMemory - afterMemory;

                    return new MemoryCleanupResult
                    {
                        Success = cleanupResult,
                        Message = cleanupResult ? $"成功清理内存，释放了 {FormatBytes(memoryFreed)}" : "内存清理失败",
                        MemoryFreed = memoryFreed,
                        BeforeMemory = beforeMemory,
                        AfterMemory = afterMemory
                    };
                }
                catch (Exception ex)
                {
                    return new MemoryCleanupResult
                    {
                        Success = false,
                        Message = $"内存清理过程中发生错误: {ex.Message}",
                        MemoryFreed = 0
                    };
                }
            });
        }

        /// <summary>
        /// 根据指定的掩码执行内存清理
        /// </summary>
        /// <param name="mask">清理掩码</param>
        /// <returns>是否成功</returns>
        public static bool CleanMemoryWithMask(uint mask)
        {
            try
            {
                if (!IsRunningAsAdministrator())
                {
                    return false;
                }

                return PerformMemoryCleanup(mask);
            }
            catch
            {
                return false;
            }
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 检查是否以管理员权限运行
        /// </summary>
        /// <returns>是否具有管理员权限</returns>
        private static bool IsRunningAsAdministrator()
        {
            try
            {
                var identity = System.Security.Principal.WindowsIdentity.GetCurrent();
                var principal = new System.Security.Principal.WindowsPrincipal(identity);
                return principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 从注册表读取清理设置
        /// 根据设置窗口的复选框状态生成清理掩码
        /// </summary>
        /// <returns>清理掩码</returns>
        private static uint GetCleanupMaskFromRegistry()
        {
            uint mask = 0;

            try
            {
                using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\MemGuardian"))
                {
                    if (key != null)
                    {
                        // 工作集
                        if (GetBooleanValue(key, "WorkingSetCleanup", true))
                            mask |= REDUCT_WORKING_SET;

                        // 系统文件缓存
                        if (GetBooleanValue(key, "SystemFileCacheCleanup", true))
                            mask |= REDUCT_SYSTEM_FILE_CACHE;

                        // 修改页列表
                        if (GetBooleanValue(key, "ModifiedPageListCleanup", false))
                            mask |= REDUCT_MODIFIED_LIST;

                        // 待机列表
                        if (GetBooleanValue(key, "StandbyListCleanup", false))
                            mask |= REDUCT_STANDBY_LIST;

                        // 待机列表（无优先级）
                        if (GetBooleanValue(key, "StandbyListNoPriorityCleanup", true))
                            mask |= REDUCT_STANDBY_PRIORITY0_LIST;

                        // 修改文件缓存
                        if (GetBooleanValue(key, "ModifiedFileCacheCleanup", true))
                            mask |= REDUCT_MODIFIED_FILE_CACHE;

                        // 注册表缓存
                        if (GetBooleanValue(key, "RegistryCacheCleanup", true))
                            mask |= REDUCT_REGISTRY_CACHE;

                        // 合并内存列表
                        if (GetBooleanValue(key, "MergedMemoryListCleanup", true))
                            mask |= REDUCT_COMBINE_MEMORY_LISTS;
                    }
                }
            }
            catch
            {
                // 如果读取注册表失败，使用默认掩码
                mask = REDUCT_MASK_DEFAULT;
            }

            // 如果没有设置任何选项，使用默认掩码
            if (mask == 0)
            {
                mask = REDUCT_MASK_DEFAULT;
            }

            return mask;
        }

        /// <summary>
        /// 从注册表键获取布尔值
        /// </summary>
        /// <param name="key">注册表键</param>
        /// <param name="valueName">值名称</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>布尔值</returns>
        private static bool GetBooleanValue(RegistryKey key, string valueName, bool defaultValue)
        {
            try
            {
                var value = key.GetValue(valueName);
                return value != null ? Convert.ToBoolean(value) : defaultValue;
            }
            catch
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// 执行内存清理操作
        /// 根据掩码执行相应的清理操作
        /// </summary>
        /// <param name="mask">清理掩码</param>
        /// <returns>是否成功</returns>
        private static bool PerformMemoryCleanup(uint mask)
        {
            bool success = true;

            try
            {
                // 清空工作集
                if ((mask & REDUCT_WORKING_SET) == REDUCT_WORKING_SET)
                {
                    success &= EmptyWorkingSets();
                }

                // 清空系统文件缓存
                if ((mask & REDUCT_SYSTEM_FILE_CACHE) == REDUCT_SYSTEM_FILE_CACHE)
                {
                    success &= EmptySystemFileCache();
                }

                // 刷新修改页列表
                if ((mask & REDUCT_MODIFIED_LIST) == REDUCT_MODIFIED_LIST)
                {
                    success &= FlushModifiedList();
                }

                // 清空待机列表
                if ((mask & REDUCT_STANDBY_LIST) == REDUCT_STANDBY_LIST)
                {
                    success &= PurgeStandbyList();
                }

                // 清空低优先级待机列表
                if ((mask & REDUCT_STANDBY_PRIORITY0_LIST) == REDUCT_STANDBY_PRIORITY0_LIST)
                {
                    success &= PurgeLowPriorityStandbyList();
                }

                // 刷新修改文件缓存
                if ((mask & REDUCT_MODIFIED_FILE_CACHE) == REDUCT_MODIFIED_FILE_CACHE)
                {
                    success &= FlushVolumeCache();
                }

                // 刷新注册表缓存
                if ((mask & REDUCT_REGISTRY_CACHE) == REDUCT_REGISTRY_CACHE)
                {
                    success &= FlushRegistryCache();
                }

                // 合并内存列表
                if ((mask & REDUCT_COMBINE_MEMORY_LISTS) == REDUCT_COMBINE_MEMORY_LISTS)
                {
                    success &= CombineMemoryLists();
                }
            }
            catch
            {
                success = false;
            }

            return success;
        }

        /// <summary>
        /// 清空工作集
        /// 释放所有进程的工作集内存
        /// </summary>
        /// <returns>是否成功</returns>
        private static bool EmptyWorkingSets()
        {
            try
            {
                var command = SystemMemoryListCommand.MemoryEmptyWorkingSets;
                var result = NtSetSystemInformation(
                    SystemInformationClass.SystemMemoryListInformation,
                    Marshal.AllocHGlobal(Marshal.SizeOf(command)),
                    (uint)Marshal.SizeOf(command));

                return result == 0;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 清空系统文件缓存
        /// 释放系统文件缓存占用的内存
        /// </summary>
        /// <returns>是否成功</returns>
        private static bool EmptySystemFileCache()
        {
            try
            {
                var cacheInfo = new SystemFileCacheInformation
                {
                    MinimumWorkingSet = new UIntPtr(0xFFFFFFFF),
                    MaximumWorkingSet = new UIntPtr(0xFFFFFFFF),
                    Flags = 0
                };

                var result = NtSetSystemInformation(
                    SystemInformationClass.SystemFileCacheInformationEx,
                    Marshal.AllocHGlobal(Marshal.SizeOf(cacheInfo)),
                    (uint)Marshal.SizeOf(cacheInfo));

                return result == 0;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 刷新修改页列表
        /// 将修改的页面写入磁盘
        /// </summary>
        /// <returns>是否成功</returns>
        private static bool FlushModifiedList()
        {
            try
            {
                var command = SystemMemoryListCommand.MemoryFlushModifiedList;
                var result = NtSetSystemInformation(
                    SystemInformationClass.SystemMemoryListInformation,
                    Marshal.AllocHGlobal(Marshal.SizeOf(command)),
                    (uint)Marshal.SizeOf(command));

                return result == 0;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 清空待机列表
        /// 释放待机列表中的内存
        /// </summary>
        /// <returns>是否成功</returns>
        private static bool PurgeStandbyList()
        {
            try
            {
                var command = SystemMemoryListCommand.MemoryPurgeStandbyList;
                var result = NtSetSystemInformation(
                    SystemInformationClass.SystemMemoryListInformation,
                    Marshal.AllocHGlobal(Marshal.SizeOf(command)),
                    (uint)Marshal.SizeOf(command));

                return result == 0;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 清空低优先级待机列表
        /// 释放低优先级待机列表中的内存
        /// </summary>
        /// <returns>是否成功</returns>
        private static bool PurgeLowPriorityStandbyList()
        {
            try
            {
                var command = SystemMemoryListCommand.MemoryPurgeLowPriorityStandbyList;
                var result = NtSetSystemInformation(
                    SystemInformationClass.SystemMemoryListInformation,
                    Marshal.AllocHGlobal(Marshal.SizeOf(command)),
                    (uint)Marshal.SizeOf(command));

                return result == 0;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 刷新卷缓存
        /// 刷新所有卷的缓存
        /// </summary>
        /// <returns>是否成功</returns>
        private static bool FlushVolumeCache()
        {
            try
            {
                // 这里简化实现，实际应该遍历所有卷
                // 由于卷缓存刷新比较复杂，这里返回true表示操作完成
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 刷新注册表缓存
        /// 刷新注册表缓存
        /// </summary>
        /// <returns>是否成功</returns>
        private static bool FlushRegistryCache()
        {
            try
            {
                var result = NtSetSystemInformation(
                    SystemInformationClass.SystemRegistryReconciliationInformation,
                    IntPtr.Zero,
                    0);

                return result == 0;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 合并内存列表
        /// 合并物理内存列表
        /// </summary>
        /// <returns>是否成功</returns>
        private static bool CombineMemoryLists()
        {
            try
            {
                var combineInfo = new MemoryCombineInformationEx
                {
                    Handle = UIntPtr.Zero,
                    PagesCombined = UIntPtr.Zero
                };

                var result = NtSetSystemInformation(
                    SystemInformationClass.SystemCombinePhysicalMemoryInformation,
                    Marshal.AllocHGlobal(Marshal.SizeOf(combineInfo)),
                    (uint)Marshal.SizeOf(combineInfo));

                return result == 0;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 获取当前内存使用情况
        /// 返回已使用的内存字节数
        /// </summary>
        /// <returns>已使用内存字节数</returns>
        private static long GetMemoryUsage()
        {
            try
            {
                using (var searcher = new System.Management.ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem"))
                {
                    foreach (System.Management.ManagementObject obj in searcher.Get())
                    {
                        var totalMemory = Convert.ToUInt64(obj["TotalVisibleMemorySize"]) * 1024;
                        var freeMemory = Convert.ToUInt64(obj["FreePhysicalMemory"]) * 1024;
                        return (long)(totalMemory - freeMemory);
                    }
                }
            }
            catch
            {
                // 如果获取失败，返回0
            }

            return 0;
        }

        /// <summary>
        /// 格式化字节数
        /// 将字节数转换为可读的格式
        /// </summary>
        /// <param name="bytes">字节数</param>
        /// <returns>格式化后的字符串</returns>
        private static string FormatBytes(long bytes)
        {
            string[] suffixes = { "B", "KB", "MB", "GB", "TB" };
            int counter = 0;
            decimal number = bytes;

            while (Math.Round(number / 1024) >= 1)
            {
                number = number / 1024;
                counter++;
            }

            return $"{number:n1} {suffixes[counter]}";
        }

        #endregion
    }

    /// <summary>
    /// 内存清理结果类
    /// 包含清理操作的详细结果信息
    /// </summary>
    public class MemoryCleanupResult
    {
        /// <summary>
        /// 是否成功
        /// </summary>
        public bool Success { get; set; }

        /// <summary>
        /// 结果消息
        /// </summary>
        public string Message { get; set; } = "";

        /// <summary>
        /// 释放的内存字节数
        /// </summary>
        public long MemoryFreed { get; set; }

        /// <summary>
        /// 清理前的内存使用量
        /// </summary>
        public long BeforeMemory { get; set; }

        /// <summary>
        /// 清理后的内存使用量
        /// </summary>
        public long AfterMemory { get; set; }
    }
}
